package cn.com.cetccst.tools.device;


import static cn.com.cetccst.tools.kv.CommonKV.kvStore;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;

import androidx.annotation.RequiresPermission;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.regex.Pattern;

import cn.com.cetccst.tools.kv.KVKeys;
import cn.com.cetccst.tools.log.CommonLogger;

public class Device {

    @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE")
    public static String getSerialNumber() {
        try {
            return Build.getSerial();
        } catch (Exception e) {
            CommonLogger.info("get serial number error", e);
        }
        return null;
    }

    @SuppressLint("HardwareIds")
    public static String getDeviceId(Context context) {

        String deviceId = null;

        if (kvStore != null) {
            deviceId = kvStore.decodeString(KVKeys.KEY_DEVICE_ID);
            if (!TextUtils.isEmpty(deviceId)) {
                return deviceId;
            }
        }

        deviceId = getSerialNumber();
        if (isValidDeviceID(deviceId)) {
            return deviceId;
        }

        TelephonyManager tm = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));

        try {
            deviceId = tm.getImei();
            if (validImeiOrMeid(deviceId)) {
                return deviceId;
            }
        } catch (Exception e) {
            CommonLogger.info("get imei error", e);
        }
        try {
            deviceId = tm.getMeid();
            if (validImeiOrMeid(deviceId)) {
                return deviceId;
            }
        } catch (Exception e) {
            CommonLogger.info("get meid error", e);
        }

        deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        if (isValidDeviceID(deviceId)) {
            return deviceId;
        }

        deviceId = UUID.randomUUID().toString();
        if (kvStore != null)
            kvStore.encode(KVKeys.KEY_DEVICE_ID, deviceId);
        return deviceId;
    }

    public static String getOsv() {
        String osV = harmonyOsv();
        if (TextUtils.isEmpty(osV)) {
            return Build.VERSION.RELEASE;
        } else {
            int index = osV.indexOf(".");
            if (index > 0) {
                return osV.substring(0, index);
            }
        }
        return "";
    }

    public static int getScreenWidth(Activity activity) {
        DisplayMetrics outMetrics = new DisplayMetrics();
        activity.getWindow().getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }

    public static boolean isRooted() {
        File f = null;
        final String kSuSearchPaths[] = {"/system/bin/", "/system/xbin/",
                "/system/sbin/", "/sbin/", "/vendor/bin/"};
        try {
            for (int i = 0; i < kSuSearchPaths.length; i++) {
                f = new File(kSuSearchPaths[i] + "su");
                if (f.exists()) {
                    return true;
                }
            }
        } catch (Exception e) {
            CommonLogger.error("isroot error", e);
            return false;
        }
        return false;
    }

    @SuppressLint("HardwareIds")
    public static String getImsi(Context context) {
        try {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                return telephonyManager != null ? telephonyManager.getSubscriberId() : null;
            }
        } catch (Exception e) {
            CommonLogger.error("get imsi error", e);
        }

        return "";
    }

    public static int getBatteryLevel(Context context) {
        BatteryManager bm = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
        int batLevel = 0;
        if (bm != null) {
            batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        }

        return batLevel;
    }


    // 获取内置存储总空间
    public static long getInternalTotalSize() {
        return getTotalSize(Environment.getDataDirectory());
    }

    // 获取内置存储可用空间
    public static long getInternalAvailableSize() {
        return getAvailableSize(Environment.getDataDirectory());
    }

    // 获取外置存储总空间
    public static long getExternalTotalSize() {
        if (isExternalStorageMounted()) {
            return getTotalSize(Environment.getExternalStorageDirectory());
        }
        return 0;
    }

    // 获取外置存储可用空间
    public static long getExternalAvailableSize() {
        if (isExternalStorageMounted()) {
            return getAvailableSize(Environment.getExternalStorageDirectory());
        }
        return 0;
    }

    // 检查外置存储是否可用
    private static boolean isExternalStorageMounted() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    //--------private
    // 计算总空间大小
    private static long getTotalSize(File path) {
        try {
            StatFs stat = new StatFs(path.getPath());
            long blockSize, totalBlocks;

            blockSize = stat.getBlockSizeLong();
            totalBlocks = stat.getBlockCountLong();
            return totalBlocks * blockSize;
        } catch (Exception e) {
            return 0;
        }
    }

    // 计算可用空间大小
    private static long getAvailableSize(File path) {
        try {
            StatFs stat = new StatFs(path.getPath());
            long blockSize, availableBlocks;

            blockSize = stat.getBlockSizeLong();
            availableBlocks = stat.getAvailableBlocksLong();
            return availableBlocks * blockSize;
        } catch (Exception e) {
            return 0;
        }
    }

    private static boolean validImeiOrMeid(String deviceId) {
        return deviceId != null && deviceId.length() >= 14
                && Pattern.matches("[\\da-fA-F]{14,}", deviceId)
                && !allSameChar(deviceId);
    }

    private static boolean isValidDeviceID(String deviceId) {
        if (deviceId == null || deviceId.isEmpty() || allSameChar(deviceId) || Build.UNKNOWN.equals(deviceId)) {
            return false;
        }
        return true;
    }

    private static boolean allSameChar(String s) {
        char c0 = s.charAt(0);
        int i, len;
        for (i = 1, len = s.length(); i < len && s.charAt(i) == c0; i++) {
        }
        return i == len;
    }

    private static String harmonyOsv() {
        return getProp("hw_sc.build.platform.version", "");
    }

    private static String getProp(String property, String defaultValue) {
        try {
            @SuppressLint("PrivateApi") Class<?> spClz = Class.forName("android.os.SystemProperties");
            Method method = spClz.getDeclaredMethod("get", String.class);
            String value = (String) method.invoke(spClz, property);
            if (TextUtils.isEmpty(value)) {
                return defaultValue;
            }
            return value;
        } catch (Throwable e) {
            CommonLogger.error("get system prop error", e);
        }
        return defaultValue;
    }
}
